package com.maruti.otterapi;

import java.io.BufferedReader;
import java.io.InputStream;
import java.io.InputStreamReader;
import java.net.HttpURLConnection;
import java.net.URL;
import java.util.HashMap;
import java.util.Map;

import com.google.gson.Gson;
import com.maruti.otterapi.authorinfo.AuthorInfoResponse;
import com.maruti.otterapi.experts.ExpertsResponse;
import com.maruti.otterapi.linkposts.LinkpostsResponse;
import com.maruti.otterapi.populartrackbacks.PopulartrackbacksResponse;
import com.maruti.otterapi.search.SearchResponse;
import com.maruti.otterapi.searchhistogram.SearchHistogramResponse;
import com.maruti.otterapi.stats.StatsResponse;
import com.maruti.otterapi.top.TopResponse;
import com.maruti.otterapi.trackbacks.TrackbacksResponse;
import com.maruti.otterapi.urlinfo.URLInfoResponse;

public class TopsyInvoker {

	public static Map<String, Class> responseMap = new HashMap<String, Class>();
	private TopsyConfig topsyConfig;
	private Map<String, String> errorMessages = new HashMap<String, String>() {
		{
			put(
					"400",
					"Parameter check failed - indicates that a required " +
					"parameter is missing or a parameter has a value that is out of bounds. ");
			put("403", "Forbidden");
			put("404", "Action not supported");
			put("500", "Unexpected internal error");
			put("503", "Temporarily unavailable");
		}
	};

	public TopsyInvoker() {
		responseMap.put("search", SearchResponse.class);
		responseMap.put("authorInfo", AuthorInfoResponse.class);
		responseMap.put("experts", ExpertsResponse.class);
		responseMap.put("searchHistogram", SearchHistogramResponse.class);
		responseMap.put("urlInfo", URLInfoResponse.class);
		responseMap.put("trackbacks", TrackbacksResponse.class);
		responseMap.put("top", TopResponse.class);
		responseMap.put("stats", StatsResponse.class);
		responseMap.put("populartrackbacks", PopulartrackbacksResponse.class);
		responseMap.put("linkposts", LinkpostsResponse.class);
		responseMap.put("listpostsCount", LinkpostsResponse.class);
	}

	public TopsyConfig getTopsyConfig() {
		return topsyConfig;
	}

	public void setTopsyConfig(TopsyConfig topsyConfig) {
		this.topsyConfig = topsyConfig;
	}

	public Object fetchData(String urlStr, String resource)
			throws Otter4JavaException {
		if (topsyConfig.isSetProxy()) {
			System.setProperty("http.proxyHost", topsyConfig.getProxyHost());
			System.setProperty("http.proxyPort", topsyConfig.getProxyPort());
		}
		System.out.println(urlStr + topsyConfig.getApiKeyCurrent());
		URL url = null;

		try {
			url = new URL(urlStr + topsyConfig.getApiKeyCurrent());
		} catch (java.net.MalformedURLException e) {
			e.printStackTrace();
			throw new Otter4JavaException(e.getMessage(), e);
		}

		HttpURLConnection conn = null;
		String json = "";
		try {
			conn = (HttpURLConnection) url.openConnection();
			
			// http timeout
			conn.setConnectTimeout(60000);
			String message = "";
			String rateLimitLimit = conn
					.getHeaderField("X-RateLimit-Limit");
			String rateLimitLimitRemaining = conn
					.getHeaderField("X-RateLimit-Remaining");
			String rateLimitLimitReset = conn
					.getHeaderField("X-RateLimit-Reset");
			message += "Limit=" + rateLimitLimit
					+ " Remaining=" + rateLimitLimitRemaining
					+ " Reset=" + rateLimitLimitReset;
			System.out.println(message);
			
			if (rateLimitLimitRemaining == null || rateLimitLimitRemaining.equals("0")) {
				System.out.println("===WARNING===\nCurrent API Key:" + topsyConfig.getApiKeys()[topsyConfig.getKeyOffset()]
						+ " has reached maximum usage or it is expired !!!\n==========");
				return null;
			}

			if (conn.getResponseCode() != 200) {
				System.out.println("Failed to get profile detail for \""
						+ "\", HTTP status: " + conn.getResponseCode() + " "
						+ conn.getResponseMessage());
				String rCode = errorMessages.get(conn.getResponseCode());
				if (rCode == null) {
					rCode = "Unknown error occured";
				}
				message = rCode + message;
				throw new Otter4JavaException(message);
			}

			InputStream obj = (InputStream) conn.getContent();

			BufferedReader br = new BufferedReader(new InputStreamReader(obj));
			String str = "";

			while ((str = br.readLine()) != null) {
				json += str;
			}
		} catch (java.io.IOException e) {
			e.printStackTrace();
			throw new Otter4JavaException(e.getMessage(), e);
		}
		// System.out.println(json);
		Gson gson = new Gson();
		return gson.fromJson(json.trim(), responseMap.get(resource));
	}
}
